// bdlb_guidutil.h                                                    -*-C++-*-
#ifndef INCLUDED_BDLB_GUIDUTIL
#define INCLUDED_BDLB_GUIDUTIL

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide functions that produce Globally Unique Identifiers.
//
//@CLASSES:
//  bdlb::GuidUtil: namespace for methods for creating GUIDs
//
//@SEE_ALSO: bdlb_guid
//
//@DESCRIPTION: This component provides a 'struct', 'bdlb::GuidUtil', that
// serves as a namespace for utility functions that create and work with
// Globally Unique Identifiers (GUIDs).
//
///Grammar for GUIDs Used in 'GuidFromString'
///------------------------------------------
// This conversion performed by 'GuidFromString' is intended to be used for
// GUIDs generated by external sources that have a variety of formats.
//
///GUID String Format
///------------------
//..
// <SPEC>             ::=  <BRACED GUID>     |   <GUID>
//
// <BRACED GUID>      ::=  '[' <GUID> ']'    |   '[ ' <GUID> ' ]'
//                         '{' <GUID> '}'    |   '{ ' <GUID> ' }'
//
// <GUID>             ::=  <FORMATTED GUID>   |   <UNFORMATTED GUID>
//
// <FORMATTED GUID>    ::=  <X>{4} '-' <X>{2} '-' <X>{2} '-' <X>{2} '-' <X>{6}
//
// <UNFORMATTED GUID> ::=  <X>{16}
//
// <X>                ::=  [0123456789ABCDEFabcdef]{2}
//
//
// EXAMPLES:
// ---------
// { 87654321-AAAA-BBBB-CCCC-012345654321 }
// 00010203-0405-0607-0809-101112131415
// [00112233445566778899aAbBcCdDeEfF]
//..
//
///Cryptographic Security
///----------------------
// 'GuidUtil' provides two families of functions for generating GUIDs:
// 'generate' and 'generateNonSecure'.  The primary difference between them is
// the cryptographic security of the resulting GUIDs and performance.  The
// slower 'generate' methods aim to produce cryptographically secure GUIDs by
// accessing underlying system resources to obtain truly random numbers,
// whereas the faster 'generateNonSecure' methods use a fast high-quality (but
// not strictly cryptographically secure) in-process random-number generator.
//
///Usage
///-----
// Suppose we are building a system for managing records for employees in a
// large international firm.  These records have no natural field which can be
// used as a unique ID, so a GUID must be created for each employee.
//
// First let us define a value-type for employees.
//..
//  class MyEmployee {
//      // This class provides a value-semantic type to represent an employee
//      // record.  These records are for internal use only.
//..
// For the sake of brevity, we provide a limited amount of data in each record.
// We additionally show a very limited scope of functionality.
//..
//      // DATA
//      bsl::string  d_name;    // name of the employee
//      double       d_salary;  // salary in some common currency
//      bdlb::Guid   d_guid;    // a GUID for the employee
//
//    public:
//      // CREATORS
//      MyEmployee(const string& name, double salary);
//          // Create an object with the specified 'name' and specified
//          //'salary', generating a new GUID to represent the employee.
//
//      // ...
//
//      // ACCESSORS
//      const bdlb::Guid& Guid() const;
//          // Return the 'guid' of this object.
//
//      const bsl::string& name() const;
//          // Return the 'name' of this object.
//
//      double salary() const;
//          // Return the 'salary' of this object.
//      // ...
//  };
//..
// Next, we create free functions 'operator<' and 'operator==' to allow
// comparison of 'MyEmployee' objects.  We take advantage of the monotonically
// increasing nature of sequential GUIDs to implement these methods.
//..
//
//  bool operator== (const MyEmployee& lhs, const MyEmployee& rhs);
//      // Return 'true' if the specified 'lhs' object has the same value as
//      // the specified 'rhs' object, and 'false' otherwise.  Note that two
//      // 'MyEmployee' objects have the same value if they have the same
//      // guid.
//
//  bool operator< (const MyEmployee& lhs, const MyEmployee& rhs);
//      // Return 'true' if the value of the specified 'lhs' MyEmployee object
//      // is less than the value of the specified 'rhs' MyEmployee object,
//      // and 'false' otherwise.  A MyEmployee object is less than another if
//      // the guid is less than the other.
// ...
//
//  // CREATORS
//  MyEmployee::MyEmployee(const string& name, double salary)
//  : d_name(name)
//  , d_salary(salary)
//  {
//      bdlb::GuidUtil::generate(&d_guid);
//  }
//
//  // ACCESSORS
//  const bdlb::Guid& MyEmployee::Guid() const
//  {
//      return d_guid;
//  }
//
//  const bsl::string& MyEmployee::name() const
//  {
//      return d_name;
//  }
//
//  double MyEmployee::salary() const
//  {
//      return d_salary;
//  }
//
//  // FREE FUNCTIONS
//  bool operator==(const MyEmployee& lhs, const MyEmployee& rhs)
//  {
//      return lhs.Guid() == rhs.Guid();
//  }
//
//  bool operator<(const MyEmployee& lhs, const MyEmployee& rhs)
//  {
//       return lhs.Guid() < rhs.Guid();
//  }
//..
// Next, we create some employees:
//..
//      MyEmployee e1("Foo Bar"    , 1011970);
//      MyEmployee e2("John Doe"   , 12345);
//      MyEmployee e3("Joe Six-pack", 1);
//..
// Finally, we verify that the generated GUIDs are unique.
//..
//      assert(e1 < e2 || e2 < e1);
//      assert(e2 < e3 || e3 < e2);
//      assert(e1 < e3 || e3 < e1);
//..

#include <bdlscm_version.h>

#include <bdlb_guid.h>

#include <bsl_cstddef.h>
#include <bsl_string.h>

#include <bsls_assert.h>
#include <bsls_types.h>

namespace BloombergLP {
namespace bdlb {

                              // ===============
                              // struct GuidUtil
                              // ===============

struct GuidUtil {
    // This 'struct' provides a namespace for functions that create Universally
    // Unique Identifiers per RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt).

    // CLASS METHODS
    static void generate(Guid *result, bsl::size_t numGuids = 1);
        // Generate a sequence of GUIDs meeting the RFC 4122 version 4
        // specification, and load the resulting GUIDs into the array referred
        // to by the specified 'result'.  Optionally specify 'numGuids',
        // indicating the number of GUIDs to load into the 'result' array.  If
        // 'numGuids' is not supplied, a default of 1 is used.  An RFC 4122
        // version 4 GUID consists of 122 randomly generated bits, two
        // "variant" bits set to '10', and four "version" bits set to '0100'.
        // The behavior is undefined unless 'result' refers to a contiguous
        // sequence of at least 'numGuids' 'Guid' objects.

    static void generate(unsigned char *result, bsl::size_t numGuids = 1);
        // Generate a sequence of GUIDs meeting the RFC 4122 version 4
        // specification, and load the bytes of the resulting GUIDs into the
        // array referred to by the specified 'result'.  Optionally specify
        // 'numGuids', indicating the number of GUIDs to load into the 'result'
        // array.  If 'numGuids' is not supplied, a default of 1 is used.  An
        // RFC 4122 version 4 GUID consists of 122 randomly generated bits, two
        // "variant" bits set to '10', and four "version" bits set to '0100'.
        // The behavior is undefined unless 'result' refers to a contiguous
        // sequence of at least '16 * numGuids' bytes.

    static Guid generate();
        // Generate and return a single GUID meeting the RFC 4122 version 4
        // specification, consisting of 122 randomly generated bits, two
        // "variant" bits set to '10', and four "version" bits set to '0100'.

    static void generateNonSecure(Guid *result, bsl::size_t numGuids = 1);
        // Generate a sequence of GUIDs meeting the RFC 4122 version 4
        // specification, and load the resulting GUIDs into the array referred
        // to by the specified 'result'.  Optionally specify 'numGuids',
        // indicating the number of GUIDs to load into the 'result' array.  If
        // 'numGuids' is not supplied, a default of 1 is used.  An RFC 4122
        // version 4 GUID consists of 122 randomly generated bits, two
        // "variant" bits set to '10', and four "version" bits set to '0100'.
        // The behavior is undefined unless 'result' refers to a contiguous
        // sequence of at least 'numGuids' 'Guid' objects.  Note that this
        // function generates high quality, albeit not cryptographically
        // secure, random numbers for GUIDs.

    static void generateNonSecure(unsigned char *result,
                                  bsl::size_t    numGuids = 1);
        // Generate a sequence of GUIDs meeting the RFC 4122 version 4
        // specification, and load the resulting GUIDs into the array referred
        // to by the specified 'result'.  Optionally specify 'numGuids',
        // indicating the number of GUIDs to load into the 'result' array.  If
        // 'numGuids' is not supplied, a default of 1 is used.  An RFC 4122
        // version 4 GUID consists of 122 randomly generated bits, two
        // "variant" bits set to '10', and four "version" bits set to '0100'.
        // The behavior is undefined unless 'result' refers to a contiguous
        // sequence of at least 'numGuids * sizeof(Guid)' characters.  Note
        // that this function generates high quality, albeit not
        // cryptographically secure, random numbers for GUIDs.

    static Guid generateNonSecure();
        // Generate and return a single GUID meeting the RFC 4122 version 4
        // specification, consisting of 122 randomly generated bits, two
        // "variant" bits set to '10', and four "version" bits set to '0100'.
        // Note that this function generates high quality, albeit not
        // cryptographically secure, random numbers for GUIDs.

    static int guidFromString(Guid *result, bslstl::StringRef guidString);
        // Parse the specified 'guidString' (in {GUID String Format}) and load
        // its value into the specified 'result'.  Return 0 if 'result'
        // successfully loaded, and non-zero otherwise.

    static Guid guidFromString(bslstl::StringRef guidString);
        // Parse the specified 'guidString' (in {GUID String Format}) and
        // return the converted GUID, or a default-constructed 'Guid' if the
        // string is improperly formatted.

    static void guidToString(bsl::string *result, const Guid& guid);
        // Serialize the specified 'guid' into the specified 'result'.  The
        // 'result' string will be in a format suitable for 'guidFromString'.

    static bsl::string guidToString(const Guid& guid);
        // Convert the specified 'guid' into a string suitable for
        // 'guidFromString', and return the string.

    static int getVersion(const bdlb::Guid& guid);
        // Return the version of the specified 'guid' object.  The behavior is
        // undefined unless the contents of the 'guid' object are compliant
        // with RFC 4122.

    static bsls::Types::Uint64 getMostSignificantBits(const Guid& guid);
        // Return the most significant 8 bytes of the specified 'guid'.

    static bsls::Types::Uint64 getLeastSignificantBits(const Guid& guid);
        // Return the least significant 8 bytes of the specified 'guid'.
};

// ============================================================================
//                      INLINE DEFINITIONS
// ============================================================================

                              // ---------------
                              // struct GuidUtil
                              // ---------------
// CLASS METHODS
inline
void GuidUtil::generate(Guid *result, bsl::size_t numGuids)
{
    generate(reinterpret_cast<unsigned char *>(result), numGuids);
}

inline
void GuidUtil::generateNonSecure(Guid *result, bsl::size_t numGuids)
{
    generateNonSecure(reinterpret_cast<unsigned char *>(result), numGuids);
}

inline
int GuidUtil::getVersion(const Guid& guid)
{
    return (guid[6] & 0xF0) >> 4;
}

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
